﻿using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing.Design;
using System.Linq;
using DevExpress.XtraGrid.Views.Grid;
using Marmat.Forms.Views.Grid;

namespace Marmat.Forms
{
    [Designer("Marmat.Forms.GridControlDesigner")]
    [ToolboxItem(true)]
    public partial class GridControl : BaseGrid, IBindingSource
    {
        public GridControl()
        {
            InitializeComponent();
        }

        /// <summary>
        /// 返回当前选中行。
        /// </summary>
        /// <returns></returns>
        [Browsable(false)]
        public object CurrentRow
        {
            get
            {
                return this.GridControl1.MainView.GetRow(this.Position);
            }
        }

        bool IBindingSource.AllowEdit
        {
            get => base.Editable;
            set => base.Editable = value;
        }

        /// <summary>
        /// 获取或设置连接器绑定到的数据源。
        /// </summary>
        /// <returns></returns>
        [Browsable(false)]
        [DefaultValue(null)]
        public override object DataSource
        {
            get
            {
                return base.DataSource;
            }

            set
            {
                int position = this.Position;
                base.DataSource = value;
                if (this.Columns.Count == 0)
                {
                    var descriptorCollection = this.BindingSource.GetItemProperties(null).OfType<PropertyDescriptor>().ToArray();
                    foreach (DevExpress.XtraGrid.Columns.GridColumn gridColumn in this.gridView1.Columns)
                    {
                        var column = new Column(gridColumn);
                        column.Name = gridColumn.FieldName;
                        column.FieldName = gridColumn.FieldName;
                        var descriptor = descriptorCollection.FirstOrDefault(x => (x.Name ?? "") == (gridColumn.FieldName ?? ""));
                        if (descriptor is object)
                        {
                            column.Caption = descriptor.Description;
                        }

                        this.Columns.Add(column);
                    }
                }

                if (position == 0)
                {
                    this.RaiseCurrentChanged();
                }
                else
                {
                    this.Position = 0;
                }
            }
        }

        /// <summary>
        /// 返回当前选中行的行号。
        /// </summary>
        /// <returns></returns>
        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public int FocusedRowHandle
        {
            get
            {
                return this.gridView1.FocusedRowHandle;
            }

            set
            {
                this.gridView1.FocusedRowHandle = value;
            }
        }


        /// <summary>
        /// 在基础列表中添加一个新项。
        /// </summary>
        /// <returns></returns>
        /// <remarks></remarks>
        public object AddNew()
        {
            var result = this.BindingSource.AddNew();
            this.EndEdit();
            return result;
        }

        /// <summary>
        /// 将现有项目添加到内部列表。
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        public int Add(object value)
        {
            int result = this.BindingSource.Add(value);
            this.EndEdit();
            return result;
        }

        private void BGridControl_CurrentChanged(object sender, Views.Grid.GridEventArgs e)
        {
            CurrentChanged?.Invoke(this, new Views.GridControl.GridEventArgs(this));
        }

        private void BGridControl_PositionChanged(object sender, Views.Grid.GridEventArgs e)
        {
            PositionChanged?.Invoke(this, new Views.GridControl.GridEventArgs(this));
        }

        private void BGridControl_BeforeShowContextMenu(object sender, Views.Grid.BeforeShowContextMenuEventArgs e)
        {
            var args = new Views.GridControl.BeforeShowContextMenuEventArgs(this, e);
            BeforeShowContextMenu?.Invoke(this, args);
        }

        private void BGridControl_CellButtonClick(object sender, Views.Grid.RowColEventArgs e)
        {
            var args = new Views.GridControl.RowColEventArgs(this, e);
            CellButtonClick?.Invoke(this, args);
        }

        private void BGridControl_CellLinkClick(object sender, MouseRowColEventArgs e)
        {
            var args = new Views.GridControl.RowColEventArgs(this, e);
            CellLinkClick?.Invoke(this, args);
        }

        private void BGridControl_CustomRowCellEdit(object sender, Views.Grid.CustomRowCellEditEventArgs e)
        {
            var args = new Views.GridControl.CustomRowCellEditEventArgs(this, e);
            CustomRowCellEdit?.Invoke(this, args);
        }

        private void BGridControl_CellMerge(object sender, Views.Grid.CellMergeEventArgs e)
        {
            var args = new Views.GridControl.CellMergeEventArgs(this, e);
            CellMerge?.Invoke(this, args);
        }

        private void BGridControl_CustomRowCellEditForEditing(object sender, Views.Grid.CustomRowCellEditEventArgs e)
        {
            var args = new Views.GridControl.CustomRowCellEditEventArgs(this, e);
            CustomRowCellEditForEditing?.Invoke(this, args);
        }

        private void BGridControl_ShowingEditor(object sender, Views.Grid.RowColCancelEventArgs e)
        {
            var args = new Views.GridControl.RowColCancelEventArgs(this, e);
            ShowingEditor?.Invoke(this, args);
        }

        private void BGridControl_ShownEditor(object sender, Views.Grid.RowColEventArgs e)
        {
            var args = new Views.GridControl.RowColEventArgs(this, e);
            ShownEditor?.Invoke(this, args);
        }

        private void BGridControl_ValidatingEditor(object sender, Views.Grid.ValidateEditEventArgs e)
        {
            var args = new Views.GridControl.ValidateEditEventArgs(this, e);
            ValidatingEditor?.Invoke(this, args);
        }

        private void BGridControl_CellValueChanging(object sender, Views.Grid.CellValueChangingEventArgs e)
        {
            var args = new Views.GridControl.CellValueChangingEventArgs(this, e);
            CellValueChanging?.Invoke(this, args);
        }

        private void BGridControl_CellValueChanged(object sender, Views.Grid.CellValueChangingEventArgs e)
        {
            var args = new Views.GridControl.CellValueChangingEventArgs(this, e);
            CellValueChanged?.Invoke(this, args);
        }

        private void BGridControl_ColumnWidthChanged(object sender, Views.Grid.ColumnEventArgs e)
        {
            var args = new Views.GridControl.ColumnEventArgs(this, e);
            ColumnWidthChanged?.Invoke(this, args);
        }

        private void BGridControl_FocusedColumnChanged(object sender, Views.Grid.FocusedColumnChangedEventArgs e)
        {
            var args = new Views.GridControl.FocusedColumnChangedEventArgs(this, e);
            FocusedColumnChanged?.Invoke(this, args);
        }

        private void BGridControl_FocusedRowChanged(object sender, Views.Grid.FocusedRowChangedEventArgs e)
        {
            var args = new Views.GridControl.FocusedRowChangedEventArgs(this, e);
            FocusedRowChanged?.Invoke(this, args);
        }

        private void BGridControl_SelectionChanged(object sender, Views.Grid.SelectionChangedEventArgs e)
        {
            var args = new Views.GridControl.SelectionChangedEventArgs(this, e);
            SelectionChanged?.Invoke(this, args);
        }

        private void BGridControl_CustomColumnDisplayText(object sender, Views.Grid.CustomColumnDisplayTextEventArgs e)
        {
            var args = new Views.GridControl.CustomColumnDisplayTextEventArgs(this, e);
            CustomColumnDisplayText?.Invoke(this, args);
        }

        private void BGridControl_CustomDrawColumnHeader(object sender, Views.Grid.ColumnHeaderCustomDrawEventArgs e)
        {
            var args = new Views.GridControl.ColumnHeaderCustomDrawEventArgs(this, e);
            CustomDrawColumnHeader?.Invoke(this, args);
        }

        private void GridControl_CustomDrawCell(object sender, Views.Grid.RowCellCustomDrawEventArgs e)
        {
            var args = new Views.GridControl.RowCellCustomDrawEventArgs(this, e.info);
            CustomDrawCell?.Invoke(this, args);
        }

        /// <summary>
        /// 获取或设置是否显示新增行
        /// </summary>
        /// <value></value>
        /// <returns></returns>
        /// <remarks></remarks>
        [DefaultValue(false)]
        [Category("行为")]
        [Description("获取或设置是否显示新增行。")]
        public bool ShowAddNew
        {
            get => this.m_ShowAddNew;
            set
            {
                if (this.m_ShowAddNew != value)
                {
                    this.m_ShowAddNew = value;
                    NewItemRowPosition newItemRowPosition = this.ShowAddNew ? NewItemRowPosition.Bottom : NewItemRowPosition.None;
                    this.BaseGridView.OptionsView.NewItemRowPosition = newItemRowPosition;
                }
            }
        }

        private bool m_ShowAddNew = false;

        /* TODO ERROR: Skipped RegionDirectiveTrivia */
        /// <summary>
        /// 获取数据源的实际绑定对象。
        /// </summary>
        /// <returns></returns>
        object IBindingSource.GetDataSource()
        {
            return this.BindingSource;
        }

        /// <summary>
        /// 获取绑定的列集合
        /// </summary>
        /// <returns></returns>
        public BindingFieldInfo[] GetColumnCollection()
        {
            var list = new List<BindingFieldInfo>();
            foreach (Column dc in this.Columns)
            {
                var column = new BindingFieldInfo()
                {
                    Name = dc.Name,
                    Caption = dc.Caption,
                    ReadOnly = !dc.AllowEdit,
                    DataType = dc.DataType
                };
                list.Add(column);
            }

            return list.ToArray();
        }
        /* TODO ERROR: Skipped EndRegionDirectiveTrivia */
        /// <summary>
        /// 获取选择的行集合的行号
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T[] GetSelectedRows<T>()
        {
            var list = new List<T>();
            var rows = this.GetSelectedRows();
            foreach (int rowHandle in rows)
            {
                var row = this.GetRow(rowHandle);
                if (row is T)
                {
                    list.Add((T)row);
                }
            }

            return list.ToArray();
        }
    }
}